package com.zwf.domain.strategy.service.raffle;

import com.zwf.domain.strategy.model.entity.RaffleAwardEntity;
import com.zwf.domain.strategy.model.entity.RaffleFactorEntity;
import com.zwf.domain.strategy.model.entity.StrategyEntity;
import com.zwf.domain.strategy.model.entity.RuleActionEntity;
import com.zwf.domain.strategy.model.valobj.RuleLogicCheckTypeVO;
import com.zwf.domain.strategy.repository.IStrategyRepository;
import com.zwf.domain.strategy.service.IRaffleStrategy;
import com.zwf.domain.strategy.service.armory.IStrategyDispatch;
import com.zwf.domain.strategy.service.rule.factory.DefaultLogicFactory;
import com.zwf.types.enums.ResponseCode;
import com.zwf.types.exception.AppException;
import lombok.extern.slf4j.Slf4j;

/**
 * @Author zwf
 * @description 抽奖策略抽象类，定义抽奖的标准流程
 * @date 2024/7/4 13:13
 */
@Slf4j
public abstract class AbstractRaffleStrategy implements IRaffleStrategy {

    // 策略仓储服务 -> domain层像一个大厨，仓储层提供米面粮油
    protected IStrategyRepository repository;
    // 策略调度服务 -> 只负责抽奖处理，通过新增接口的方式，隔离职责，不需要使用方关心或者调用抽奖的初始化
    protected IStrategyDispatch strategyDispatch;

    //TODO 此处构造函数注入有什么好处
    public AbstractRaffleStrategy(IStrategyRepository repository, IStrategyDispatch strategyDispatch) {
        this.repository = repository;
        this.strategyDispatch = strategyDispatch;
    }


    @Override
    public RaffleAwardEntity performRaffle(RaffleFactorEntity raffleFactorEntity) {
        //1、参数校验
        Long userId = raffleFactorEntity.getUserId();
        Long strategyId = raffleFactorEntity.getStrategyId();
        if(strategyId == null || userId == null) {
            throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(),ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }

        //2、策略查询
        StrategyEntity strategyEntity = repository.queryStrategyEntity(strategyId);

        //3、抽奖前规则过滤
        RuleActionEntity<RuleActionEntity.RaffleBeforeEntity> ruleActionEntity = this.doCheckRaffleBeforeLogic(RaffleFactorEntity.builder()
                .userId(userId).strategyId(strategyId).build(), strategyEntity.ruleModels());

        //4、规则被接管情况
        if (RuleLogicCheckTypeVO.TAKE_OVER.getCode().equals(ruleActionEntity.getCode())) {
            if (DefaultLogicFactory.LogicModel.RULE_BLACKLIST.getCode().equals(ruleActionEntity.getRuleModel())) {
                // 黑名单返回固定的奖品ID
                return RaffleAwardEntity.builder()
                        .awardId(ruleActionEntity.getData().getAwardId())
                        .build();
            } else if (DefaultLogicFactory.LogicModel.RULE_WIGHT.getCode().equals(ruleActionEntity.getRuleModel())) {
                // 根据返回的权重信息进行抽奖
                RuleActionEntity.RaffleBeforeEntity raffleBeforeEntity = ruleActionEntity.getData();
                String ruleWeightValueKey = raffleBeforeEntity.getRuleWeightValueKey();
                Integer awardId = strategyDispatch.getRandomAwardIdByRuleWeight(strategyId, ruleWeightValueKey);
                return RaffleAwardEntity.builder()
                        .awardId(awardId)
                        .build();
            }
        }

        //5、默认抽奖流程
        Integer awardId = strategyDispatch.getRandomAwardId(strategyId);

        return RaffleAwardEntity.builder()
                .awardId(awardId)
                .build();
    }

    protected abstract RuleActionEntity<RuleActionEntity.RaffleBeforeEntity> doCheckRaffleBeforeLogic(RaffleFactorEntity raffleFactorEntity, String... logics);
}
